using SkeletonNET.Crud;
using SkeletonNET.Crud.Repository;
using Microsoft.Practices.ServiceLocation;
using System.Linq;
using SkeletonNET.Crud.KeyCache;

namespace SkeletonNET.Base.Crud.CrudManager
{
    public class CrudManager<TEntity> : ICrudManager<TEntity>
        where TEntity : class, IEntity, new()
    {
        private IEntityKeyCache keyCache;
        private IRepository<TEntity> repository;
        protected IRepository<TEntity> Repository
        {
            get { return repository = repository ?? ServiceLocator.Current.GetInstance<IRepository<TEntity>>(); }
            set { repository = value; }
        }
        protected IEntityKeyCache KeyCache
        {
            get { return keyCache = keyCache ?? ServiceLocator.Current.GetInstance<IEntityKeyCache>(); }
            set { keyCache = value; }
        }

        public virtual TEntity Update(TEntity entity)
        {
            return Repository.Update(entity);
        }

        public virtual void Delete(TEntity entity)
        {
            Repository.Delete(entity);
        }

        public virtual void DeleteByID(object id)
        {
            Repository.DeleteByID(id);
        }

        public virtual TEntity Insert(TEntity entity)
        {
            return Repository.Insert(entity);
        }

        public System.Collections.Generic.IEnumerable<TEntity> All(System.Linq.Expressions.Expression<System.Func<TEntity, bool>> expr = null)
        {
            var sub = Repository
                .GetQuery();
            if (expr != null)
                sub.Where(expr);

            return sub.ToList();
        }
        
        public TEntity GetByID(object id)
        {
            return repository.GetByID(id);
        }

        public TEntity InsertOrUpdate(TEntity entity)
        {
            var getKeyValue = KeyCache.GetKeyValue(entity);
            if ((int)getKeyValue != 0)
                return Update(entity);
            else
                return Insert(entity);
        }

        public void Save()
        {
            if (repository != null)
                Repository.Save();
        }
    }
}